import Compiler from "./compiler";
import defaults from "./defaults";
import TemplateError from "./error";

var debugRender = function debugRender(error, options) {
  options.onerror(error, options);

  var render = function render() {
    return "{Template Error}";
  };

  render.mappings = [];
  render.sourcesContent = [];
  return render;
};
/**
 * 编译模版
 * @param {string|Object} source   模板内容
 * @param {?Object}       options  编译选项
 * @return {function}
 */


var compile = function compile(source) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  var newOptions = options;

  if (typeof source !== 'string') {
    newOptions = source;
  } else {
    newOptions.source = source;
  } // 合并默认配置


  newOptions = defaults.$extend(newOptions);
  var newSource = newOptions.source; // debug 模式

  /* istanbul ignore if */

  if (newOptions.debug === true) {
    newOptions.cache = false;
    newOptions.minimize = false;
    newOptions.compileDebug = true;
  }

  if (newOptions.compileDebug) {
    newOptions.minimize = false;
  } // 转换成绝对路径


  if (newOptions.filename) {
    newOptions.filename = newOptions.resolveFilename(newOptions.filename, newOptions);
  }

  var _newOptions = newOptions,
      filename = _newOptions.filename;
  var _newOptions2 = newOptions,
      cache = _newOptions2.cache;
  var _newOptions3 = newOptions,
      caches = _newOptions3.caches; // 匹配缓存

  if (cache && filename) {
    var _render = caches.get(filename);

    if (_render) {
      return _render;
    }
  } // 加载外部模板


  if (!newSource) {
    try {
      newSource = newOptions.loader(filename, newOptions);
      newOptions.newSource = newSource;
    } catch (e) {
      var error = new TemplateError({
        name: 'CompileError',
        path: filename,
        message: "template not found: ".concat(e.message),
        stack: e.stack
      });

      if (newOptions.bail) {
        throw error;
      } else {
        return debugRender(error, newOptions);
      }
    }
  }

  var fn;
  var compiler = new Compiler(newOptions);

  try {
    fn = compiler.build();
  } catch (error) {
    var err = new TemplateError(error);

    if (newOptions.bail) {
      throw err;
    } else {
      return debugRender(err, newOptions);
    }
  }

  var render = function render(data, blocks) {
    try {
      return fn(data, blocks);
    } catch (error) {
      // 运行时出错以调试模式重载
      if (!newOptions.compileDebug) {
        newOptions.cache = false;
        newOptions.compileDebug = true;
        return compile(newOptions)(data, blocks);
      }

      var _err = new TemplateError(error);

      if (newOptions.bail) {
        throw _err;
      } else {
        return debugRender(_err, newOptions)();
      }
    }
  };

  render.mappings = fn.mappings;
  render.sourcesContent = fn.sourcesContent;

  render.toString = function () {
    return fn.toString();
  };

  if (cache && filename) {
    caches.set(filename, render);
  }

  return render;
};

compile.Compiler = Compiler;
export default compile;